<cfcomponent displayname="fifoCache" output="false" namespace="org.rickosborne.util" hint="First-In-First-Out Cache" extends="fifoCache">
	<cfset this.Expirations=StructNew()>
	<cffunction name="init" displayname="init" output="false" description="Initialize our object" returntype="fifoCache">
		<cfset super.init()>
		<cfreturn this>
	</cffunction>
	<cffunction name="Put" displayname="Put" output="false" description="Put an item into the cache" returntype="numeric">
		<cfargument name="Key" required="true" type="any">
		<cfargument name="Value" required="false" type="any" default="">
		<cfargument name="Expiry" required="false" type="numeric" default="">
		<cfset var ex=DateAdd("h",1,Now())>
		<cfset var ret=super.Put(Arguments.Key,Arguments.Value)>
		<cfif IsNumeric(Arguments.Expiry)><cfset ex=DateAdd("s",Arguments.Expiry,Now())></cfif>
		<cfset this.Expirations[Arguments.Key]=ex>
		<cfreturn ret>
	</cffunction>
	<cffunction name="Delete" displayname="Delete" output="false" description="Delete an item from the cache" returntype="numeric">
		<cfargument name="Key" required="true" type="string">
		<cfset var ret=super.Delete(Arguments.Key)>
		<cfset StructDelete(this.Expirations,Arguments.Key,false)>
		<cfreturn ret>
	</cffunction>
	<cffunction name="Exists" displayname="Exists" output="true" description="Find an item in the cache" returntype="boolean">
		<cfargument name="Key" required="true" type="string">
		<cfset var ret=false>
		<cflock name="#this.GUID#" type="READONLY" timeout="5" throwontimeout="false">
			<cfif StructKeyExists(this.Cache,Arguments.Key) AND StructKeyExists(this.Expirations,Arguments.Key) AND (this.Expirations[Arguments.Key] GTE Now())>
				<cfset ret=true>
			</cfif>
		</cflock>
		<cfreturn ret>
	</cffunction>
</cfcomponent>